home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / programm / GNU_C++ / LIB / CFLIB-11.LZH / src / wdial.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-04  |  12.9 KB  |  618 lines

  1.  
  2. #include "intern.h"
  3.  
  4. #ifdef __MTAES__
  5. #define wind_create_grect(a,b)    wind_create(a,b)
  6. #define wind_calc_grect(a,b,c,d)    wind_calc(a,b,c,d)
  7. #define wind_open_grect(a,b)        wind_open(a,b)
  8. #define wind_set_str(a,b,c)        wind_set_string(a,b,c)
  9. #endif
  10.  
  11. static WDIALOG        *wdial_list = NULL;
  12.  
  13. /*** lokale Funktionen *********************************************************/
  14.  
  15. /*
  16. static void dump_list(void)
  17. {
  18.     WDIALOG    *p;
  19.     int        i = 0;
  20.     
  21.     p = wdial_list;
  22.     if (p == NULL)
  23.         debug("Liste ist leer\n");
  24.     while (p != NULL)
  25.     {
  26.         debug("%d: %s\n",i, p->win_name);
  27.         p = p->next;
  28.         i++;
  29.     }
  30. }
  31. */
  32.  
  33.  
  34. /*
  35.  * Liefert zu einem Fensterhandle den Dialog oder NULL.
  36. */
  37. static WDIALOG *get_wdial(int w_handle)
  38. {
  39.     WDIALOG    *p;
  40.     
  41.     p = wdial_list;
  42.     while (p != NULL)
  43.     {
  44.         if (p->win_handle == w_handle)
  45.             return p;
  46.         p = p->next;
  47.     }
  48.     return NULL;
  49. }
  50.  
  51.  
  52. /*
  53.  * Zeichnet Dialog neu.
  54. */
  55. static void draw_wdial(WDIALOG *wd, int obj, int depth, int x, int y, int w, int h)
  56. {
  57.     GRECT        r, r1;
  58.     OBJECT    *tree;
  59.     
  60.     r.g_x = x;
  61.     r.g_y = y;
  62.     r.g_w = w;
  63.     r.g_h = h;
  64.  
  65.     if (wd->mode & WD_ICON)
  66.         tree = wd->icon;
  67.     else
  68.         tree = wd->tree;
  69.  
  70.     wind_update(BEG_UPDATE);
  71.     graf_mouse(M_OFF, NULL);
  72.     wind_get_grect(wd->win_handle, WF_FIRSTXYWH, &r1);
  73.     while (r1.g_w != 0 && r1.g_h != 0)
  74.     {
  75.         if (rc_intersect(&r, &r1))
  76. #ifdef __MTAES__
  77.             objc_draw(tree, obj, depth, &r1);
  78. #else
  79.             objc_draw(tree, obj, depth, r1.g_x, r1.g_y, r1.g_w, r1.g_h);
  80. #endif
  81.         wind_get_grect(wd->win_handle, WF_NEXTXYWH, &r1);
  82.     }
  83.     graf_mouse(M_ON, NULL);
  84.     wind_update(END_UPDATE);
  85. }
  86.  
  87.  
  88. /*
  89.  * Zeichnet den Cursor neu.
  90.  * Der doppelte objc_edit() ist für den Fall, wenn der Cursor teilweise
  91.  * oder ganz von einem anderen Fenster verdeckt wird.
  92. */
  93. static void draw_cursor(WDIALOG *wd, int mode)
  94. {
  95.     GRECT    r;
  96.     
  97.     if (wd != NULL && wd->edit_obj > 0)
  98.     {
  99.         objc_edit(wd->tree, wd->edit_obj, 0, &wd->edit_idx, mode);
  100.         get_objframe(wd->tree, wd->edit_obj, &r);
  101.         draw_wdial(wd, ROOT, MAX_DEPTH, r.g_x, r.g_y-3, r.g_w+1, r.g_h+6);
  102.         objc_edit(wd->tree, wd->edit_obj, 0, &wd->edit_idx, mode);
  103.     }
  104. }
  105.  
  106.  
  107. static void move_wdial(WDIALOG *wd, int new_x, int new_y)
  108. {
  109.     if (wd != NULL)
  110.     {
  111.         GRECT    r;
  112.         
  113.         wind_get_grect(wd->win_handle, WF_CURRXYWH, &r);
  114.         r.g_x = new_x;
  115.         r.g_y = new_y;
  116.         wind_set_grect(wd->win_handle, WF_CURRXYWH, &r);
  117.         wind_get_grect(wd->win_handle, WF_WORKXYWH, &r);
  118.     
  119.         if (wd->mode & WD_ICON)
  120.         {
  121.             wd->icon[0].ob_x = r.g_x;
  122.             wd->icon[0].ob_y = r.g_y;
  123.         }
  124.         else
  125.         {
  126.             wd->tree[0].ob_x = r.g_x;
  127.             wd->tree[0].ob_y = r.g_y - wd->delta_y;
  128.             wd->work.g_x = r.g_x;
  129.             wd->work.g_y = r.g_y;
  130.             wd->work.g_w = r.g_w;
  131.             wd->work.g_h = r.g_h;
  132.         }
  133.     }
  134. }
  135.  
  136.  
  137. static void iconify_wdial(WDIALOG *wd, int x, int y, int w, int h)
  138. {
  139.     if (wd->icon && !(wd->mode & WD_ICON))
  140.     {
  141.         /* alte Größe merken */
  142.         wind_get_grect(wd->win_handle, WF_CURRXYWH, &wd->work);
  143.  
  144.         wind_set(wd->win_handle, WF_ICONIFY, x, y, w, h);
  145.         wind_get(wd->win_handle, WF_WORKXYWH, &x, &y, &w, &h);
  146.         wd->icon[0].ob_x = x;
  147.         wd->icon[0].ob_y = y;
  148.         wd->icon[0].ob_width = w;
  149.         wd->icon[0].ob_height = h;
  150.         wd->icon[1].ob_x = (w - wd->icon[1].ob_width) / 2;
  151.         wd->icon[1].ob_y = (h - wd->icon[1].ob_height) / 2;
  152.         wd->mode |= WD_ICON;
  153.     }
  154. }
  155.  
  156.  
  157. static void uniconify_wdial(WDIALOG *wd, int x, int y, int w, int h)
  158. {
  159.     if (wd->mode & WD_ICON)
  160.     {
  161.         if (x == -1)
  162.             wind_set_grect(wd->win_handle, WF_UNICONIFY, &wd->work);
  163.         else
  164.             wind_set(wd->win_handle, WF_UNICONIFY, x, y, w, h);
  165.         wind_get_grect(wd->win_handle, WF_WORKXYWH, &wd->work);
  166.         wd->mode &= ~WD_ICON;
  167.     }
  168. }
  169.  
  170.  
  171. /*
  172.  * Ruft Exit-Callback auf und schließ ggf. den Dialog.
  173. */
  174. static void call_cb(WDIALOG *wd)
  175. {
  176.     int    close = TRUE;
  177.     int    obj;
  178.     
  179.     obj = wd->next_obj;
  180.     if (wd->exit_cb != NULL)
  181.         close = (wd->exit_cb)(wd, obj);
  182.     if (close)
  183.     {
  184.         obj &= 0x7FFF;
  185.         if (obj != WD_CLOSER)
  186.             set_state(wd->tree, obj, SELECTED, FALSE);
  187.         close_wdial(wd);
  188.     }
  189. }
  190.  
  191.  
  192. /*** exportierte Funktionen ****************************************************/
  193.  
  194. /*
  195.  * Dialog vorbereiten.
  196. */
  197. WDIALOG *create_wdial(OBJECT *tree, OBJECT *icon, int edit_obj,
  198.                                 WDIAL_OCB open_cb, WDIAL_XCB exit_cb)
  199. {
  200.     WDIALOG    *new;
  201.     int        d;
  202.     
  203.     new = (WDIALOG *) cf_malloc(sizeof(WDIALOG), "create_wdial", FALSE);
  204.     if (new != NULL)
  205.     {
  206.         /* in die Liste hängen */
  207.         new->next = wdial_list;
  208.         wdial_list = new;
  209.         
  210.         new->tree = tree;
  211.         new->icon = icon;
  212.         new->mode = 0;
  213.         new->win_handle = -1;
  214.         if (new->icon == NULL)
  215.             new->win_kind = (NAME|MOVER|CLOSER);
  216.         else
  217.             new->win_kind = (NAME|MOVER|CLOSER|SMALLER);
  218.         
  219.         /*
  220.          * Titelzeile suchen und als Fenstertitel merken. 
  221.         */
  222.         if (get_magx_obj(tree, 1) == MX_UNDERLINE)
  223.         {
  224.             new->title_obj = 1;
  225.             get_string(tree, new->title_obj, new->win_name);
  226.         }
  227.         else
  228.         {
  229.             new->title_obj = -1;
  230.             strcpy(new->win_name, "*** kein Titel! ***");
  231.         }
  232.  
  233.         /*
  234.          * Gibt es ein Abbruch-Button? -> Closer
  235.         */
  236.         d = find_flag(tree, FLAG11);
  237.         if (d != -1)
  238.             new->cancel_obj = d;
  239.         else    
  240.             new->cancel_obj = WD_CLOSER;
  241.  
  242.         new->next_obj    = 0;
  243.         if ((edit_obj <= 0) || !edit_valid(new->tree, edit_obj))
  244.             new->edit_obj = find_edit(new->tree, 0, FMD_FORWARD);
  245.         else
  246.             new->edit_obj = edit_obj;
  247.         new->edit_idx    = 0;
  248.  
  249.         new->open_cb    = open_cb;
  250.         new->exit_cb    = exit_cb;
  251.     }
  252.     return new;
  253. }
  254.  
  255.  
  256. /*
  257.  * Dialog entfernen.
  258. */
  259. void delete_wdial(WDIALOG *wd)
  260. {
  261.     if (wd != NULL)
  262.     {
  263.         WDIALOG    *p;
  264.         
  265.         if (wd->win_handle > 0)
  266.         {
  267.             close_wdial(wd);
  268.             wind_delete(wd->win_handle);
  269.             wd->win_handle = -1;
  270.         }
  271.         
  272.         /* aus Liste löschen */
  273.         if (wd == wdial_list)        /* erster? */
  274.             wdial_list = wd->next;
  275.         else
  276.         {
  277.             p = wdial_list;
  278.             while (p->next != NULL && p->next != wd)
  279.                 p = p->next;
  280.             p->next = wd->next;
  281.         }
  282.         Mfree(wd);
  283.     }
  284. }
  285.  
  286.  
  287. /*
  288.  * Dialog-Fenster öffnen.
  289. */
  290. void open_wdial(WDIALOG *wd, int pos_x, int pos_y)
  291. {
  292.     GRECT    r1, r2;
  293.     int    d;
  294.     
  295.     if (wd != NULL)
  296.     {
  297.         if (wd->mode == WD_OPEN)                        /* ist schon offen */
  298.         {
  299.             wind_set(wd->win_handle, WF_TOP, 0, 0, 0, 0);
  300.             return;
  301.         }
  302.         if (wd->mode & WD_ICON)                            /* ist iconified */
  303.         {
  304.             uniconify_wdial(wd, -1, 0, 0, 0);
  305.             return;
  306.         }
  307.         if (wd->mode & WD_SHADE)                        /* ist shaded */
  308.         {
  309.             wind_set(wd->win_handle, WF_SHADE, 0, 0, 0, 0);
  310.             wd->mode &= ~WD_SHADE;
  311.             return;
  312.         }
  313.         else if (wd->win_handle > 0)                    /* war schon mal offen */
  314.         {
  315.             if (wd->open_cb != NULL)
  316.                 (wd->open_cb)(wd);
  317.             wind_calc_grect(WC_BORDER, wd->win_kind, &wd->work, &r1);
  318.             wind_open_grect(wd->win_handle, &r1);
  319.             wd->mode = WD_OPEN;
  320.             return;
  321.         }
  322.         else                                                    /* alles neu */
  323.         {
  324.             /* Rahmen abschalten */
  325.             wd->tree[0].ob_spec.obspec.framesize = 0;
  326.  
  327.             if ((pos_x == -1) || (pos_y == -1))        /* Zentrieren */
  328. #ifdef __MTAES__
  329.                 form_center(wd->tree, &r1);    
  330. #else
  331.                 form_center(wd->tree, &r1.g_x, &r1.g_y, &r1.g_w, &r1.g_h);    
  332. #endif
  333.             else
  334.             {
  335.                 wd->tree[0].ob_x = pos_x;
  336.                 wd->tree[0].ob_y = pos_y;
  337.             }
  338.             
  339.             r1.g_x = wd->tree[0].ob_x;
  340.             r1.g_y = wd->tree[0].ob_y;
  341.  
  342.             /* Titel nicht mitzeichnen */
  343.             if (wd->title_obj != -1)
  344.             {
  345.                 wd->delta_y = (wd->tree[wd->title_obj].ob_y + wd->tree[wd->title_obj].ob_height);
  346.                 wd->tree[0].ob_y -= wd->delta_y;
  347.                 set_flag(wd->tree, wd->title_obj, HIDETREE, TRUE);
  348.             }
  349.             else
  350.                 wd->delta_y = 0;
  351.  
  352.             r1.g_w = wd->tree[0].ob_width;
  353.             r1.g_h = wd->tree[0].ob_height - wd->delta_y;
  354.  
  355.             wind_calc_grect(WC_BORDER, wd->win_kind, &r1, &r2);
  356.  
  357.             /* Fenster neu zentrieren */
  358.             d = (r2.g_h - r1.g_h) / 2 + wd->delta_y / 2;
  359.             r2.g_y += d ;
  360.             wd->tree[0].ob_y += d;
  361.             /* herausragen ins Menü verhindern */
  362.             if (r2.g_y < gl_desk.g_y)
  363.             {
  364.                 wd->tree[0].ob_y += (gl_desk.g_y - r2.g_y);
  365.                 r2.g_y = gl_desk.g_y;
  366.             }
  367.  
  368.             wd->win_handle = wind_create_grect(wd->win_kind, &r2);
  369.             if (wd->win_handle > 0)
  370.             {
  371.                 wind_set_str(wd->win_handle, WF_NAME, wd->win_name);
  372.                 if (wd->open_cb != NULL)
  373.                     (wd->open_cb)(wd);
  374.                 wind_open_grect(wd->win_handle, &r2);
  375.                 wind_calc_grect(WC_WORK, wd->win_kind, &r2, &wd->work);
  376.                 wd->mode = WD_OPEN;
  377.             }
  378.             else
  379.                 form_alert(1, "[3][wdial.Open:|Kein Fenster mehr frei!][oops]");
  380.         }
  381.     }
  382. }
  383.  
  384.  
  385. /*
  386.  * Dialog-Fenster schließen.
  387. */
  388. void close_wdial(WDIALOG *wd)
  389. {
  390.     if (wd != NULL)
  391.     {
  392.         if ((wd->win_handle > 0) && (wd->mode & WD_OPEN))
  393.         {
  394.             wind_close(wd->win_handle);
  395.             wd->mode = 0;
  396.         }
  397.     }
  398. }
  399.  
  400.  
  401. /*
  402.  * Einzelne Objekte neu zeichnen.
  403. */
  404. void redraw_wdobj(WDIALOG *wd, int obj)
  405. {
  406.     GRECT    r;
  407.     
  408.     if (wd != NULL && !(wd->mode & WD_ICON) && !(wd->mode & WD_SHADE))
  409.     {
  410.         get_objframe(wd->tree, obj, &r);
  411.         draw_wdial(wd, ROOT, MAX_DEPTH, r.g_x, r.g_y, r.g_w, r.g_h);
  412.  
  413.         /* neu zeichnen, wenn obj das Editfeld bzw. ein Child von obj ist */
  414.         if ((obj == wd->edit_obj) ||
  415.              (wd->edit_obj >= wd->tree[obj].ob_head && wd->edit_obj <= wd->tree[obj].ob_tail))
  416.             draw_cursor(wd, ED_INIT);
  417.     }
  418. }
  419.  
  420. /*
  421.  * Ein Objekt im iconified Dialog zeichnen.
  422. */
  423. void redraw_wdicon(WDIALOG *wd, int obj)
  424. {
  425.     GRECT    r;
  426.     
  427.     if (wd != NULL && wd->mode & WD_ICON)
  428.     {
  429.         get_objframe(wd->icon, obj, &r);
  430.         draw_wdial(wd, ROOT, MAX_DEPTH, r.g_x, r.g_y, r.g_w, r.g_h);
  431.     }
  432. }
  433.  
  434. /*
  435.  * Cursor updaten
  436. */
  437. void change_wdedit(WDIALOG *wd, int new)
  438. {
  439.     int    last = 0;
  440.     
  441.     if (wd != NULL)
  442.     {
  443.         /* 1. prüfen, ob aktuelles nicht mehr gültig ist */
  444.         if (wd->edit_obj > 0)
  445.         {
  446.             last = -1;
  447.             if (!edit_valid(wd->tree, wd->edit_obj))
  448.             {
  449.                 objc_edit(wd->tree, wd->edit_obj, 0, &wd->edit_idx, ED_END);
  450.                 last = wd->edit_obj;
  451.             }
  452.         }
  453.         
  454.         /*
  455.          * last = -1    -> aktuelles Editfeld weiterhin gültig, nix weiteres tun
  456.          * last = 0        -> bisher kein Editfeld, erstes suchen
  457.          * last > 0        -> aktuelles Editfeld ungültig geworden, nächstes suchen
  458.         */
  459.         if (last != -1)
  460.         {
  461.             if (new > 0 && edit_valid(wd->tree, new))
  462.                 wd->edit_obj = new;            /* 2a. ein gültiges neues übergeben? */
  463.             else                                    /* 2b. neues suchen */
  464.                 wd->edit_obj = find_edit(wd->tree, last, FMD_FORWARD);
  465.             if (wd->edit_obj > 0)
  466.               objc_edit(wd->tree, wd->edit_obj, 0, &wd->edit_idx, ED_INIT);
  467.         }
  468.     }
  469. }
  470.  
  471.  
  472. /*
  473.  * Event-Verarbeitung.
  474. */
  475. int message_wdial(int *msg)
  476. {
  477.     int        ret = TRUE;
  478.     WDIALOG    *wd;
  479.     
  480.     wd = get_wdial(msg[3]);
  481.     if (wd != NULL)
  482.     {
  483.         switch (msg[0])
  484.         {
  485.             case WM_REDRAW :
  486.                 draw_wdial(wd, ROOT, MAX_DEPTH, msg[4], msg[5], msg[6], msg[7]);
  487.                 draw_cursor(wd, ED_INIT);
  488.                 break;
  489.                 
  490.             case WM_MOVED:
  491.                 move_wdial(wd, msg[4], msg[5]);
  492.                 break;
  493.  
  494.             case WM_TOPPED:
  495.                 wind_set(wd->win_handle, WF_TOP, 0, 0, 0, 0);
  496.                 break;
  497.  
  498.             case WM_BOTTOMED:
  499.                 wind_set(wd->win_handle, WF_BOTTOM, 0, 0, 0, 0);
  500.                 break;
  501.  
  502.             case WM_ICONIFY :
  503.                 iconify_wdial(wd, msg[4], msg[5], msg[6], msg[7]);
  504.                 break;
  505.  
  506.             case WM_UNICONIFY :
  507.                 uniconify_wdial(wd, msg[4], msg[5], msg[6], msg[7]);
  508.                 break;
  509.  
  510.             case WM_SHADED :
  511.                 wd->mode |= WD_SHADE;
  512.                 break;
  513.                 
  514.             case WM_UNSHADED :
  515.                 wd->mode &= ~WD_SHADE;
  516.                 break;
  517.  
  518.             case WM_CLOSED :
  519.                 wd->next_obj = wd->cancel_obj;
  520.                 call_cb(wd);
  521.                 break;
  522.  
  523.             case WM_UNTOPPED :
  524.             case WM_ONTOP :
  525.             case WM_NEWTOP:
  526.                 /* ignore */
  527.                 break;
  528.  
  529.             default:
  530.                 ret = FALSE;
  531.         }
  532.     }
  533.     else
  534.         ret = FALSE;
  535.     return ret;
  536. }
  537.  
  538.  
  539. int click_wdial(int clicks, int x, int y, int kshift, int mbutton)
  540. {
  541.     int        wh;
  542.     int        ret = TRUE, cont;
  543.     int        obj;
  544.     WDIALOG    *wd;
  545.     
  546.     wh = wind_find(x, y);
  547.     wd = get_wdial(wh);
  548.     if (wd != NULL && wd->mode == WD_OPEN)
  549.     {
  550.         if (mbutton == 1)
  551.         {
  552.             obj = cf_objc_find(wd->tree, ROOT, MAX_DEPTH, x, y);
  553.             if (obj > -1)
  554.             {
  555.                 cont = form_button(wd->tree, obj, clicks, &wd->next_obj);
  556.                 if (cont && (get_flag(wd->tree, wd->next_obj, EDITABLE)))
  557.                 {
  558.                     objc_edit(wd->tree, wd->edit_obj, 0, &wd->edit_idx, ED_END);
  559.                     wd->edit_obj = wd->next_obj;
  560.                     if (gl_magx)
  561.                         objc_edit(wd->tree, wd->edit_obj, x, &wd->edit_idx, ED_CRSR);
  562.                     else
  563.                         objc_edit(wd->tree, wd->edit_obj, 0, &wd->edit_idx, ED_INIT);
  564.                 }
  565.                 else if (!cont)
  566.                 {
  567.                     if (clicks == 2)
  568.                         wd->next_obj |= 0x8000;
  569.                     call_cb(wd);
  570.                 }
  571.             }
  572.             else
  573.                 Bconout(2, 7);
  574.         }
  575.         else if (mbutton == 2)        /* Rechtsklick ignorieren */
  576.             ret = TRUE;
  577.     }
  578.     else
  579.         ret = FALSE;
  580.     return ret;
  581. }
  582.  
  583.  
  584. int key_wdial(int kreturn, int kstate)
  585. {
  586.     int        wh, d;
  587.     int        ret = TRUE, cont, ctrl;
  588.     WDIALOG    *wd;
  589.     
  590.     wind_get(0, WF_TOP, &wh, &d, &d, &d);
  591.     wd = get_wdial(wh);
  592.     if (wd != NULL && wd->mode == WD_OPEN)
  593.     {
  594.         cont = cf_form_keybd(wd->tree, wd->edit_obj, kstate, &kreturn, &wd->next_obj);
  595.         if (cont)
  596.         {
  597.             if (kreturn)
  598.                 cf_objc_edit(wd->tree, wd->edit_obj, kreturn, &wd->edit_idx, ED_CHAR, kstate, &ctrl);
  599.             else if (cont && (wd->tree[wd->next_obj].ob_flags & EDITABLE))
  600.             {
  601.                 objc_edit(wd->tree, wd->edit_obj, 0, &wd->edit_idx, ED_END);
  602.                 wd->edit_obj = wd->next_obj;
  603.                 objc_edit(wd->tree, wd->edit_obj, 0, &wd->edit_idx, ED_INIT);
  604.             }
  605.         }
  606.         else
  607.             call_cb(wd);
  608.  
  609.         /* alle Ctrl-Codes außer ^X^C^V werden nicht ausgewertet */
  610.         if ((kstate & K_CTRL) && !ctrl)
  611.             ret = FALSE;
  612.     }
  613.     else
  614.         ret = FALSE;
  615.  
  616.     return ret;
  617. }
  618.